/**
 * 更新 url 中的页面参数
 * @param {string} url 待处理的 url
 * @param {object} params 待更新的页面参数
 * @param {object} config 配置更新策略，默认值 config.override = true
 */
function update(url, params, config) {
  const {
    path,
    search,
    hash,
  } = parseURL(url);
  const newSearch = updateSearch(search, params, config);
  return path + newSearch + hash;
}

/**
 * 删除 URL 中制定的页面参数，参数由 key 指定
 * @param {string} url 待处理的 url
 * @param {string|Array.<string>} keys 待删除的键值
 */
function del(url, keys) {
  const {
    path,
    search,
    hash,
  } = parseURL(url);

  const newSearch = delSearch(search, keys);

  return path + newSearch + hash;
}

/**
 * 更新页面字符串，search 不包含 params 的数值，则增加
 * @param {string} search
 * @param {object} params
 * @param {object} config
 * @returns {string}
 */
function updateSearch(search, params, config) {
  const searchObj = parseSearch(search);
  let newSearchObj = { ...searchObj, ...params };
  if (config && config.override === false) {
    newSearchObj = { ...params, ...searchObj };
  }
  return stringifySearch(newSearchObj);
}

/**
 * 解析页面参数
 * @param {string} search
 * @returns {object}
 */
function parseSearch(search) {
  if (!search) return {};

  const res = {};
  search = search.replace(/^\?/, '');
  const pairs = search.split('&');
  pairs.forEach(item => {
    const [key, value] = item.split('=');
    res[key] = value;
  })

  return res;
}

/**
 * 将对象连接成符合规范的页面参数
 * @param {object} params
 */
function stringifySearch(params) {
  if (!params) return '';
  const keys = Object.keys(params);
  if (keys.length <= 0) return '';

  const res = keys
    .filter(key => params[key])
    .map(key => {
      return key + '=' + params[key];
    });

  if (!res || res.length <= 0) return '';

  return '?' + res.join('&');
}

/**
 * 删除指定的键值
 * @param {string} search
 * @param {string|Array.<string>} keys
 */
function delSearch(search, keys) {
  if (!keys || keys.length <= 0) return search;

  const searchObj = parseSearch(search);
  if (typeof keys === 'string') {
    keys = [keys];
  }
  const newSearchObj = { ...searchObj };
  keys.forEach(key => {
    if (newSearchObj.hasOwnProperty(key)) {
      delete newSearchObj[key];
    }
  })

  return stringifySearch(newSearchObj);
}

/**
 * 将 URL 拆分为 path, search, hash 三部分
 * @param {string} url
 */
function parseURL(url) {
  if (!url) return null;

  let path = url;
  let search = '';
  let hash = '';

  const hashIndex = url.indexOf('#');
  const searchIndex = url.indexOf('?');

  if (hashIndex !== -1) {
    hash = path.slice(hashIndex);
    path = path.slice(0, hashIndex);
  }

  if (searchIndex !== -1) {
    search = path.slice(searchIndex);
    path = path.slice(0, searchIndex);
  }

  return {
    path,
    search,
    hash
  }
}

/**
 * 根据文件地址后缀分类
 * @param url
 * @returns {string}
 */
function urlSorter(url){
  let ext = url.split('?')[0].split('.').pop();
  ext = ext.toLowerCase()
  if (/\.(gif|jpg|jpeg|png)$/.test(ext)) {
    return 'IMG';
  } else if (/\.(mp4|wmv|avi|mpeg)$/.test(ext)){
    return 'VIDEO'
  } else if (/\.(mp3|wav|mid)$/.test(ext)){
    return 'AUDIO'
  } else if (/\.(txt|xlsx|docx|wps|doc|ppt|wrod)$/.test(ext)){
    return 'TXT'
  } else {
    return 'FOLDER'
  }
}

/**
 * 是否是绝对地址
 */
function isExternal(path) {
  return /^(https?:|mailto:|tel:)/.test(path)
}

/**
 * 
 * @desc   对象序列化
 * @param  {Object} param 
 * @return {String}
 */
function stringfyQueryString (param) {
    let _res = parse(param);
    function parse(param, prefix) {
      let res = res || '';
      prefix = prefix || '';
      for (let key in param) {
        let d = param[key];
        switch (typeof d) {
          // 字符串
          case 'string': {
            if (prefix) {
              res += prefix + '[' + key + ']' + '=' + d + '&';
            } else {
              res += key + '=' + d + '&';
            }
          } break;
          // 数组、字典
          case 'object': {
            if (d.length != undefined) {
              for (let i in d) {
                let _d = d[i];
                if (prefix) {
                  res += prefix + '[' + key + ']' + '[]=' + _d + '&';
                } else {
                  res += key + '[]=' + _d + '&';
                }
              }
            } else {
              res += parse(d, key);
            }
          } break;
          default: {
            if (prefix) {
              res += prefix + '[' + key + ']' + '=' + d + '&';
            } else {
              res += key + '=' + d + '&';
            }
          } break;
        }
      }
      return res;
    }
    return _res ? _res.substr(0, _res.length - 1) : '';
  }

export default {
  update,
  del,
  parseURL,
  parseSearch,
  stringifySearch,
  isExternal,
  urlSorter,
  stringfyQueryString
}
